import {
  Component,
  Host,
  h,
  Prop,
  Element,
  Listen,
  ComponentInterface,
  Event,
  EventEmitter,
  VNode,
} from '@stencil/core';
import { ContextMenuItem, ContextMenuOptions } from '../../interface';

/**
 * 系统上下文菜单
 *
 * @export
 * @class ContextMenu
 */
@Component({
  tag: 'context-menu',
  styleUrl: 'context-menu.scss',
  shadow: true,
})
export class ContextMenu implements ComponentInterface {
  @Element()
  el: HTMLContextMenuElement;
  /**
   * 子菜单
   *
   * @author chitanda
   * @date 2021-03-18 15:03:38
   * @type {HTMLContextMenuElement}
   */
  childEl: HTMLContextMenuElement;
  /**
   * 子菜单对象数据
   *
   * @author chitanda
   * @date 2021-03-18 16:03:25
   * @type {ContextMenuItem}
   */
  childData: ContextMenuItem;
  /**
   * 配置参数
   *
   * @author chitanda
   * @date 2021-03-18 10:03:19
   * @type {ContextMenuOptions}
   */
  @Prop()
  options: ContextMenuOptions = {
    zIndex: 1000,
    minWidth: 230,
    subOpenType: 'hover',
  };
  /**
   * 菜单数据
   *
   * @type {ContextMenuItem[]}
   * @memberof ContextMenu
   */
  @Prop()
  menus: ContextMenuItem[] = [];
  /**
   * 当为子菜单是，展示的位置
   *
   * @author chitanda
   * @date 2021-03-18 17:03:25
   * @type {('left' | 'right')}
   */
  @Prop()
  position: 'left' | 'right' = 'right';
  /**
   * 是否悬浮在菜单中
   *
   * @memberof ContextMenu
   */
  @Prop()
  hover = false;
  /**
   * 是否在悬浮态
   *
   * @author chitanda
   * @date 2021-03-18 15:03:44
   */
  @Prop()
  isHover = () => {
    if (this.childEl) {
      return this.childEl.isHover() || this.hover;
    }
    return this.hover;
  };
  /**
   * 菜单项点击
   *
   * @author chitanda
   * @date 2021-03-18 11:03:56
   * @type {EventEmitter<ContextMenuItem>}
   */
  @Event()
  itemClick: EventEmitter<ContextMenuItem>;
  /**
   * 组件挂载完毕
   *
   * @author chitanda
   * @date 2021-03-18 16:03:24
   * @type {EventEmitter<void>}
   */
  @Event()
  didLoad: EventEmitter<void>;

  @Listen('mouseenter')
  mouseenter(): void {
    this.el.hover = true;
  }

  @Listen('mouseleave')
  mouseleave(): void {
    this.el.hover = false;
  }

  @Listen('contextmenu')
  contextmenu(e: MouseEvent): void {
    e.preventDefault();
    e.stopPropagation();
  }

  /**
   * 打开子菜单
   *
   * @author chitanda
   * @date 2021-03-18 15:03:28
   * @param {MouseEvent} e
   * @param {ContextMenuItem} item
   */
  openSubMenu(e: MouseEvent, item: ContextMenuItem): void {
    e.stopPropagation();
    if (this.childEl && this.childData === item) {
      return;
    }
    this.destroyChild();
    const path = e.composedPath();
    this.childData = item;
    // 创建子菜单
    this.childEl = document.createElement('context-menu');
    this.childEl.options = this.options;
    this.childEl.menus = item.children;
    this.childEl.addEventListener('didLoad', () => {
      // 计算子菜单位置
      if (path.length > 0) {
        const el = path[0] as HTMLDivElement;
        let x = this.el.offsetLeft + this.el.offsetWidth;
        if (innerWidth - x < this.childEl.offsetWidth || this.position === 'left') {
          x -= this.el.offsetWidth;
          x -= el.offsetWidth;
          setTimeout(() => {
            this.childEl.position = 'left';
          });
        }
        let y = this.el.offsetTop + el.offsetTop;
        if (y + this.childEl.offsetHeight > innerHeight) {
          y = innerHeight - this.childEl.offsetHeight;
        }
        this.childEl.style.left = x + 'px';
        this.childEl.style.top = y - 5 + 'px';
      }
    });
    this.childEl.addEventListener('itemClick', (e: CustomEvent) => {
      this.itemClick.emit(e.detail);
    });
    document.body.appendChild(this.childEl);
  }

  /**
   * 销毁子菜单
   *
   * @author chitanda
   * @date 2021-03-18 15:03:17
   */
  destroyChild = (): void => {
    if (this.childEl) {
      document.body.removeChild(this.childEl);
      this.childEl = undefined;
    }
  };

  disconnectedCallback(): void {
    this.destroyChild();
  }

  componentDidLoad(): void {
    this.didLoad.emit();
  }

  /**
   * 绘制菜单项内容区
   *
   * @author chitanda
   * @date 2022-03-23 18:03:12
   * @param {ContextMenuItem} item
   * @return {*}  {*}
   */
  renderMenuItemContent(item: ContextMenuItem): any {
    return [
      <div class='menu-item-icon'>
        <context-menu-icon icon={item.icon} />
      </div>,
      <div class='menu-item-label'>
        <div class='label-left'>{item.text}</div>
        <div class='label-right'>{item.textRight}</div>
      </div>,
    ];
  }

  /**
   * 绘制标准子菜单
   *
   * @author chitanda
   * @date 2022-03-23 18:03:05
   * @param {number} i
   * @param {ContextMenuItem} item
   * @return {*}  {VNode}
   */
  renderSubMenuItem(i: number, item: ContextMenuItem): VNode {
    const contents: VNode[] = [
      this.renderMenuItemContent(item),
      <div class='menu-item-expand-icon'>
        <svg
          class='icon'
          viewBox='0 0 1024 1024'
          version='1.1'
          xmlns='http://www.w3.org/2000/svg'
          width='14'
          height='14'
        >
          <path d='M665.003 512L353.835 200.832a42.667 42.667 0 0 1 60.33-60.33L755.5 481.834a42.667 42.667 0 0 1 0 60.33L414.165 883.5a42.667 42.667 0 1 1-60.33-60.331L665.003 512z' />
        </svg>
      </div>,
    ];
    if (this.options.subOpenType === 'click') {
      return (
        <div
          key={i}
          class={{ 'context-menu-item': true, disable: item.disable, enable: !item.disable }}
          title={item.tooltip}
          onClick={e => {
            if (item.disable) {
              return;
            }
            this.openSubMenu(e, item);
          }}
        >
          {contents}
        </div>
      );
    }
    return (
      <div
        key={i}
        class={{ 'context-menu-item': true, disable: item.disable, enable: !item.disable }}
        title={item.tooltip}
        onMouseEnter={e => {
          if (item.disable) {
            return;
          }
          this.openSubMenu(e, item);
        }}
      >
        {contents}
      </div>
    );
  }

  /**
   * 绘制嵌入子菜单，图标模式
   *
   * @author chitanda
   * @date 2022-03-23 18:03:24
   * @param {number} i
   * @param {ContextMenuItem} item
   * @return {*}  {VNode}
   */
  renderEmbedIconSub(i: number, item: ContextMenuItem): VNode {
    return (
      <div key={i} class='context-menu-item embed-icon'>
        <div class='embed-icon--header'>{item.text}</div>
        <div class='embed-icon--content'>
          <div class='embed-icon--items'>
            {item.children.map(subItem => {
              return (
                <div class='embed-icon--item' title={subItem.tooltip} onClick={() => this.itemClick.emit(subItem)}>
                  <context-menu-icon icon={subItem.icon} />
                </div>
              );
            })}
          </div>
        </div>
      </div>
    );
  }

  /**
   * 绘制菜单项
   *
   * @author chitanda
   * @date 2022-03-23 18:03:58
   * @param {number} i
   * @param {ContextMenuItem} item
   * @return {*}  {VNode}
   */
  renderMenuItem(i: number, item: ContextMenuItem): VNode {
    if (item.type === 'separator') {
      return <div key={i} class='context-menu-item-line'></div>;
    }
    if (item.children?.length > 0) {
      if (item.subMode === 'embed-icon') {
        return this.renderEmbedIconSub(i, item);
      }
      return this.renderSubMenuItem(i, item);
    }
    return (
      <div
        key={i}
        class={{ 'context-menu-item': true, disable: item.disable, enable: !item.disable }}
        title={item.tooltip}
        onClick={() => this.itemClick.emit(item)}
        onMouseEnter={this.destroyChild}
      >
        {this.renderMenuItemContent(item)}
      </div>
    );
  }

  render(): VNode {
    return (
      <Host
        class='context-menu-container'
        style={{
          'z-index': this.options.zIndex + '',
          'min-width': this.options.minWidth + 'px',
          'max-height': innerHeight + 'px',
        }}
      >
        <div class='context-menu'>{this.menus.map((item, i) => this.renderMenuItem(i, item))}</div>
      </Host>
    );
  }
}
